<?php


namespace App\Services;


use App\Constants\CodeData;
use App\Constants\LoginTypeCode;
use App\Dao\CityIpDao;
use App\Dao\UserActiveDao;
use App\Dao\UserDao;
use App\Exception\MessageException;
use App\Model\InformationCollect;
use App\Model\OceanEngineActive;
use App\Model\PushAssistant;
use App\Model\User;
use App\Model\UserActive;
use App\Model\UserCardPack;
use App\Model\UserDel;
use App\Model\UserLock;
use App\Services\Login\AppleLoginService;
use App\Services\Login\GoogleLoginService;
use App\Services\Sms\SmsService;
use App\Services\YunXinCloud\WyyClientService;
use App\Utils\FunUtil;
use App\Utils\LoggerUtil;
use App\Utils\MemcacheClient;
use Hyperf\Di\Annotation\Inject;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use function Hyperf\Translation\trans;

class LoginService
{

    #[Inject]
    public UserDao $userDao;
    #[Inject]
    public UserActiveDao $userActiveDao;

    /**
     * Note - 退出登录
     * DateTime 2024/7/17 18:55
     * User Admin
     * @param mixed $uid
     * @return array
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function loginOut(mixed $uid)
    {
        $update['online'] = 0;
        $token = (new WyyClientService())->refreshUser($uid);
        if ($token) {
            $update['token'] = $token;
        }
        $update['session_id'] = null;
        LoggerUtil::write('logout', $update);
        LoggerUtil::write('logout', $uid);
        User::query()->where('id', $uid)->update($update); //下线

        MemcacheClient::getInstance()->delete('userInfo_' . $uid);
        return formatData(['result' => 2]);
    }


    /**
     * Note - 登录注册入口
     * DateTime 2024/7/10 10:18
     * User Admin
     * @param mixed $account
     * @param mixed $code
     * @param $type
     * @param array $commonParams
     * @return array
     */
    public function main(mixed $account, mixed $code, $type, array $commonParams)
    {
        if ($commonParams['uid'] > 0 && $commonParams['session_id'] != '') {
            // 登录
            $user = User::query()->where('id', $commonParams['uid'])->where('session_id', $commonParams['session_id'])->first();
            $commonParams['login_addr'] = 1;
        } else {
            // 判断是登录还是注册，返回用户信息
            $user = $this->userLoginOrRegister($account, $code, $type, $commonParams);
        }
        switch ($user['isdel']) {
            case 0:
                // 登陆成功处理
                $userInfo = $this->loginHandle($user, $commonParams);
                $userInfo = $this->loginSuccess($userInfo, $commonParams);
                $userInfo = $this->injectWyyUser($userInfo);
                $userInfo = $this->resetNickname($userInfo);
                return formatData(['result' => 1, 'msg' => $userInfo]);

            case 1:
                throw new MessageException(trans("desc.该账号已被删除", ['id' => $user['id']], $commonParams['language']));
            case 2:
                $user = UserDao::getInstance()->findUserInfoCache($user['id']);
                // 账号需要完善信息，直接更新用户session_id
                $user = $this->userDao->updateSessionId($user, $commonParams);
                // 将用户id注入网易云信IM
                $user = $this->injectWyyUser($user);
                return formatData(['result' => 1, 'msg' => $user], 200, CodeData::JUMP_PERFECT_DATA, '请先完善资料');
            default:
                throw new MessageException(trans("desc.该账号状态异常", ['id' => $user['id']], $commonParams['language']));
        }

    }

    /**
     * Note - 登陆前预处理
     * DateTime 2024/7/16 10:13
     * User Admin
     * @param $user
     * @param $commonParams
     * @return array
     */
    public function loginHandle($user, $commonParams): array
    {
        if ($user['sex'] == 1 && time() - $user['login_time'] > 15 * 24 * 3600) {
            UserCardPack::query()->insert([
                'get_type' => 2,    //来源：1-新人活动；2-回归奖励
                'card_type' => 1,
                'uid' => $user['id'],
                'get_time' => time(),
                'status' => 0,
            ]);
            // redis 推送消息 TODO
            $msgs = json_encode(['event' => 'back_user', 'msg' => ['uid' => $user['id']]]);
            PushMessageService::putYunXinSendAttachMsgQueue(100000, $user['id'], $msgs);
        }

        if ($user['guild_num'] == 'yq00125') {
            return formatData([
                'show_customer_service' => '0', 'uid' => $user['id'], 'nickname' => $user['nickname']
            ], 200, CodeData::DATA_ABNORMAL, '账号已被永久封禁');
        }

        //欢遇停更，男用户充值1千以上做强更寻聊，1千以下进不了APP，点击启动页就自动弹出APP
        if ($commonParams['package'] == 'com.love.huanyu' && $user['sex'] == 1 && $user['recharge'] < 1000) {
            throw new MessageException('无法登录');
        }
        return $user->toArray();
    }

    /**
     * Note - 重置昵称
     * DateTime 2024/7/16 10:22
     * User Admin
     * @param $user
     * @return array
     */
    public function resetNickname($user)
    {
        // 昵称重置后发送一次小秘书 TODO
        if ($user['nickname'] == $user['id']) {
            $pushInfo = PushAssistant::query()->where('uid', $user['id'])->first();
            if (empty($pushInfo)) {
                //记录推送
                $pushAssistantInsertData = [
                    'uid' => $user['id'],
                    'is_push' => 1,
                    'create_time' => time(),
                    'push_time' => time(),
                ];
                PushAssistant::query()->insert($pushAssistantInsertData);
                $assistantData['content'] = "您的昵称在平台内为属于重复昵称，现已被重置，请重新编辑一个新昵称";
                $assistantData['content_type'] = 1;
                FunUtil::socket_client('assistant_uid', $user['id'], '', $assistantData);
            }
        }
        return $user;
    }

    /**
     * Note - 获取用户渠道
     * DateTime 2024/7/4 10:30
     * User Admin
     * @param $oaid
     * @param $imei
     * @param string $channel
     * @return string
     */
    public function getChannel($oaid, $imei, string $channel = ''): string
    {
        $time = strtotime("-1 day");
        $date = date('Y-m-d H:i:s', $time);

        if (!empty($oaid)) {
            $channel = OceanEngineActive::query()->where('oaid', $oaid)->where('time', '>=', $date)->value('channel');
        }
        if (empty($channel) && !empty($imei)) {
            $channel = OceanEngineActive::query()->where('imei', $imei)->where('time', '>=', $date)->value('channel');
        }
        if (empty($channel) && !empty($oaid)) {
            $channel = InformationCollect::query()->where('oaid', $oaid)->where('ctime', '>', $time)->value('channel');

        }
        if (empty($channel) && !empty($imei)) {
            $channel = InformationCollect::query()->where('imei', $imei)->where('ctime', '>', $time)->value('channel');
        }

        return $channel ?? '';
    }

    private function userLoginOrRegister(mixed $account, mixed $code, $type, array $commonParams)
    {
        switch ($type) {
            case LoginTypeCode::PHONE_REGISTER_LOGIN:
                SmsService::validateCode($account, $code);
                $user = User::query()->where('phone', $account)->first();
                $commonParams['phone'] = $account;
                break;

            case LoginTypeCode::WECHAT_REGISTER_LOGIN:
                // $wxUserInfo = $this->getWxUserInfo($code);
                // $user = $userModel->findOne("select * from tb_user where wx_openid='{$wxUserInfo['openid']}' union all select * from tb_user where wx_unionid='{$wxUserInfo['unionid']}' limit 1");
                // if (!empty($user) && empty($user['wx_unionid'])) {
                //     $userModel->update($user['id'], ['wx_unionid' => $wxUserInfo['unionid']]);
                // }
                break;
            case LoginTypeCode::TOKEN_LOGIN: //这个特殊处理
                // $payload = \lib\services\user\JwtService::verifyToken($account);
                // if (!$payload) \Tool::JSON(400, array('result' => 1), 'session_id过期');
                // $user = $userModel->find('*', 'session_id=?', [$account]);
                // if (empty($user) || $payload['uid'] != $user['id']) \Tool::JSON(400, array('result' => 2), '请先登录');
                break;
            case LoginTypeCode::ONE_CLICK_LOGIN: // 一键登录
                // if (empty($commonParams['accessToken']) || empty($commonParams['ydToken'])) {
                //     \Tool::JSON(400, array('result' => 1), '一键登录参数错误');
                // }
                // $phone_data = (new \YdClient())->oneClickCheck($commonParams["accessToken"], $commonParams["ydToken"]);
                // if ($phone_data['code'] == 200 && isset($phone_data['data']['phone']) && !empty($phone_data['data']['phone'])) {
                //     $account = $phone_data['data']['phone'];
                //     $commonParams['phone'] = $account;
                //     $user = $userModel->find('*', 'phone = ?', [$account]);
                // } else {
                //     \Tool::JSON(400, array('result' => 4), '获取手机号失败！');
                // }
                break;
            case LoginTypeCode::IMEI_LOGIN:  // 设备号登录
                if (empty($commonParams['imei'])) {
                    throw new MessageException('设备号必需');
                }
                $commonParams['imei_login'] = $commonParams['imei'];
                $user = User::query()->where('imei_login', $commonParams['imei_login'])->first();
                break;

            case LoginTypeCode::APPLE_LOGIN:  // 苹果账号登录
                if (empty($commonParams['appleId']) || empty($commonParams['accessToken'])) {
                    throw new MessageException('苹果ID\CODE 不能为空！');
                }
                $appleUserInfo = AppleLoginService::getAppleInfo($commonParams['appleId'], $commonParams['code']);
                if (empty($appleUserInfo)) {
                    throw new MessageException('苹果登录验证失败！');
                }
                $commonParams['appleId'] = $appleUserInfo['appleId'];
                $user = User::query()->where('appleId', $commonParams['appleId'])->first();
                break;

            case LoginTypeCode::ALI_ONE_CLICK_LOGIN: // 阿里云一键登录
                // if (empty($commonParams['accessToken'])) {
                //     \Tool::JSON(400, array('result' => 1), '一键登录参数错误');
                // }
                // $phone_data = AliyunPns::oneClickGetMobile($commonParams["accessToken"]);
                // $param = $_REQUEST;
                // unset($param['session_id'], $param['encode_data']);
                // logInfo('one_click_login', ['param' => $param, 'result' => $phone_data]);
                // if ($phone_data['Code'] == "OK" && isset($phone_data['GetMobileResultDTO']['Mobile']) && !empty($phone_data['GetMobileResultDTO']['Mobile'])) {
                //     $account = $phone_data['GetMobileResultDTO']['Mobile'];
                //     $commonParams['phone'] = $account;
                //     $user = $userModel->find('*', 'phone = ?', [$account]);
                // } else {
                //     \Tool::JSON(400, array('result' => 4), '获取手机号失败！');
                // }
                break;

            case LoginTypeCode::PASSWORD_LOGIN: // 账号密码登录
                // if (empty($account) || empty($commonParams['password'])) {
                //     throw new MessageException('账号或密码不能为空！', 200);
                // }
                $password = md5($commonParams['password'] . PASS_SALT);

                $user = User::query()->where('phone', $account)->where('password', $password)->first();

                if (empty($user)) {
                    throw new MessageException('账号或密码不正确');
                }
                break;

            case LoginTypeCode::UMENG_ONE_CLICK: // 友盟一键登录
                // if (empty($commonParams['accessToken'])) {
                //     \Tool::JSON(400, array('result' => 1), '一键登录参数错误');
                // }
                // $phone_data = Umeng::getMobile($commonParams['accessToken']);
                // logInfo("umeng_login", $phone_data);
                // if (is_array($phone_data) && $phone_data['success'] && $phone_data['code'] == 2001 && $phone_data['data']['mobile']) {
                //     $account = $phone_data['data']['mobile'];
                //     $commonParams['phone'] = $account;
                //     $user = $userModel->find('*', 'phone = ?', [$account]);
                // } else {
                //     \Tool::JSON(400, array('result' => 4), '获取手机号失败！');
                // }
                break;

            case LoginTypeCode::GOOGLE_LOGIN: // google登录
                if (empty($commonParams['accessToken'])) {
                    throw new MessageException('google_token不能为空！');
                }
                $googleUserInfo = GoogleLoginService::getGoogleInfo($commonParams['accessToken']);

                if (empty($googleUserInfo)) throw new MessageException('google登录验证失败！');
                $commonParams['googleId'] = $googleUserInfo['googleId'];
                $user = User::query()->where('googleId', $commonParams['googleId'])->first();
                break;

            default:
                throw new MessageException('登录方式错误');
        }

        if (!empty($user)) {
            // 用户存在，检查账号状态，账号正常返回用户信息
            // 检测账号封禁状态
            $this->checkUserLockStatus($user, $commonParams);

            // 判断是否异地登录
            if ($user['sex'] == 1 && $commonParams['version_code'] >= 105) {
                $lastLoginInfo = UserActive::query()->where('uid', $user['id'])->orderBy('ctime', 'desc')->first();
                if ($lastLoginInfo) {
                    $lastLoginCity = CityIpDao::getInstance()->getProvinceCity($lastLoginInfo['ip']);
                    if ($commonParams['imei'] != $lastLoginInfo['imei'] && $lastLoginCity['city'] != $commonParams['city']) {
                        throw new MessageException('请先完成认证', CodeData::NEED_TIPS, ['result' => in_array($user['is_cardAuth'], [1, 3]) ? 22 : 21, 'msg' => $user]);
                    }
                }
            }

            return $user;
        } else {
            // 用户不存在开始注册，注册后返回用户信息
            return $this->userDao->registerInsertData($commonParams);
        }

    }

    /**
     * Note - 登录成功
     * DateTime 2024/7/16 10:13
     * User Admin
     * @param $user
     * @param $commonParams
     */
    private function loginSuccess($user, $commonParams)
    {
        //禁止登录规则
        $current_time = time();

        // 短信召回赠送金币 TODO
        // \Fun::smsRecall($user['id'], $user['phone'], $current_time);

        // 登录后注销取消
        if ($user['sex'] == 1) {
            UserDel::query()->where('uid', $user['id'])->update(['delete_time' => 0, 'status' => 0]);
        }
        // 有邀请人的女用户，3天不登录，再次登陆变为D级
        if (($user['sex'] == 2) && ($user['push_level'] == 0) && !empty($user['inviteUid']) && ($current_time - $user['login_time'] > 86400 * 3)) {
            $uid = $user['id'];
            $user['push_level'] = 1;
            User::query()->where('id', $uid)->update(['push_level' => 1]);
        }
        //缓存最新用户信息
        MemcacheClient::getInstance()->delete('userInfo_' . $user['id']);
        $user = $this->userDao->findUserInfoCache($user['id']);

        //验证添加用户活跃数据
        $this->userActiveDao->validateAddActive([
            'date' => date('Y-m-d'),
            'uid' => $user['id'],
            'ip' => $commonParams['ip'] ?? '',
            'imei' => $commonParams['imei'],
            'channel' => $commonParams['channel'],
        ]);

        // web端登录的不修改session_id
        if ($commonParams['login_from'] == 'web' && JwtService::verifyToken($user['session_id'])) {
            return $user;
        }

        //登录成功通知
        // $this->loginSuccessMsg($user);
        return $this->userDao->updateSessionId($user, $commonParams);
    }

    /**
     * Note - 注册刷新网易云信账号
     * DateTime 2024/7/16 10:14
     * User Admin
     * @param $user
     * @return mixed
     */
    private function injectWyyUser($user)
    {
        // 重置网易云信IM token
        $token = (new WyyClientService())->refreshUser($user["id"]);
        if (empty($token)) {
            // 网易云信IM账号
            $token = (new WyyClientService())->createUser($user["id"]);
        }
        if (!empty($token)) {
            $user["token"] = $token;
            User::query()->where('id', $user["id"])->update(['token' => $user["token"]]);
        }
        return $user;
    }


    private function loginSuccessMsg($user)
    {
        //发送消息列表
        $send_list = [];
        // if ($user['is_identity'] == 1) {
        // 关注用户上线消息
        $userList = $this->userDao->message($user, 4);
        if (!empty($userList)) $send_list = $userList;
        // }

        // 发送密友消息
        $send_list_close = $this->userDao->message($user, 11);

        // 上线后发送已过期消息
        if ($user['sex'] == 1) {
            (new \MessageAction())->sendExpireMsg($user['id']);
        }
    }

    /**
     * Note - 检测账号封禁状态
     * DateTime 2024/7/16 10:15
     * User Admin
     * @param $user
     * @param array $commonParams
     */
    private function checkUserLockStatus($user, array $commonParams)
    {
        if ($user['status'] == 1) {
            throw new MessageException('账号已被封禁！用户ID：' . $user['id'],
                400,
                ['uid' => $user['id'], 'nickname' => $user['nickname'], 'remark' => $user['lock_remark'], 'show_customer_service' => '0']
            );
        }
        if ($user['status'] == 2) {
            throw new MessageException("账号被永久封禁！用户ID：{$user['id']}",
                400,
                ['uid' => $user['id'], 'nickname' => $user['nickname'], 'remark' => $user['lock_remark'], 'show_customer_service' => '0']
            );
        }

        $uid = $user['id'];
        $ip = $commonParams['ip'];
        $imei = $commonParams['imei'];
        $res = UserLock::query()->where(function ($query) use ($uid) {
            $query->where('uid', $uid)->whereIn('type', [3, 4, 5]);
        })->orWhere(function ($query) use ($imei) {
            $query->where('imei', $imei)->where('type', 4);
        })->orWhere(function ($query) use ($ip) {
            $query->where('ip', $ip)->where('type', 5);
        })->where('status', 1)->first();


        if ($res) {
            $res['reason'] = str_replace(['封禁：账号, ', '封禁：账号,设备,Ip, ', '封禁：账号,设备,', '封禁：账号,Ip,'], '', $res['reason']);
            if ($res['uid'] == $user['id']) {
                $type_text = $res['type'] == 3 ? '账号' : ($res['type'] == 4 ? "设备" : "IP");
                throw new MessageException("当前 {$type_text} 已被封禁！用户ID：" . $user['id'],
                    400,
                    ['show_customer_service' => '0', 'uid' => $user['id'], 'nickname' => $user['nickname'], 'remark' => $res['reason']]
                );
            } else {
                $type_text = $res['type'] == 4 ? "设备" : "IP";
                throw new MessageException("当前 {$type_text} 因 {$res['reason']} 已被封禁，请联系客服！", 400);
            }
        }
    }

    /**
     * Note - 禁止登录的账号
     * DateTime 2024/7/10 10:04
     * User Admin
     * @param $imei
     * @param $account
     * @param $province
     * @param $inviteUid
     */
    public function banLogin($imei, $account, $province, $inviteUid)
    {
        if (in_array($imei, ['23c5a143-713d-3747-8766-70e7fdf738a7', 'c27f6e5c-59cd-3dc1-abe8-47343c9e1f14', 'f01e891f-5976-3d19-93e8-33fff0054486']) || $account == '19939808056') {
            throw new MessageException('黑名单');
        }

        if (!empty($account)) {
            $prefix = substr($account, 0, 3);
            if (in_array($prefix, [162, 165, 167, 170, 171]) && !in_array($account, ['17111498666', '16789957923'])) {
                throw new MessageException('网络繁忙，请稍后再试');
            }
        }

        if (!empty($account) && !in_array($account, ['15236959913', '18259837637'])) {
            $userInfo = User::query()->select(['id', 'sex', 'province', 'city', 'isdel', 'inviteUid'])->where('phone', $account)->orderBy('id', 'desc')->first();
            if (
                ($userInfo['sex'] == 2)
                && (
                    FunUtil::checkBlockLoginProvince($userInfo['province'], $userInfo['id'])
                    || FunUtil::checkBlockLoginProvince($province, $userInfo['id'])
                )
            ) {
                throw new MessageException('网络繁忙，稍后再试');
            }
            if (
                (empty($inviteUid) && empty($userInfo['inviteUid']))
                && $userInfo['id'] != 112811
                && (!empty($userInfo) && $userInfo['sex'] == 1 && $userInfo['isdel'] != 2 && $userInfo['recharge'] == 0)
                && (str_contains($userInfo['province'], '河南') || str_contains($userInfo['province'], '安徽'))
            ) {
                throw new MessageException('网络繁忙，稍后再试');
            }
        }
    }


}